package cn.quang.search.admin.service.impl;

import cn.quang.search.admin.entity.dto.Operator;
import cn.quang.search.admin.entity.dto.Result;
import cn.quang.search.admin.entity.po.*;
import cn.quang.search.admin.entity.vo.dic.FieldDicRequest;
import cn.quang.search.admin.mapper.*;
import cn.quang.search.admin.service.IEntityFieldDicService;
import cn.quang.search.admin.service.ISearchConfigChangeService;
import cn.quang.search.admin.service.common.RedisService;
import cn.quang.search.admin.utils.AssertUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author:  Entity Generator
 * @since:  2024-02-27 19:03:42
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class EntityFieldDicService implements IEntityFieldDicService {
	
	private final EntityLogicTableMapper entityLogicTableMapper;
	private final EntityFieldDicMapper entityFieldDicMapper;
	private final EntityLogicTableFieldDicMapper entityLogicTableFieldDicMapper;
	private final SearchResultFetcherMapper searchResultFetcherMapper;
	private final SearchResultFetcherFieldDicRelationMapper searchResultFetcherFieldDicRelationMapper;
	private final SearchSceneInnerFetcherFieldConfigMapper searchSceneInnerFetcherFieldConfigMapper;
	private final SearchSceneConfigMapper searchSceneConfigMapper;
	private final SearchSceneInnerFetcherConfigMapper searchSceneInnerFetcherConfigMapper;
	private final SearchScenePresetConditionConfigMapper searchScenePresetConditionConfigMapper;
	private final SearchSceneMapper searchSceneMapper;

	private final ISearchConfigChangeService searchConfigChangeService;
	private final RedisService redisService;

	private static final String LOCK_KEY = "CRM3$ENTITY_FIELD_DIC$";
	private static final int EXPIRE_SECONDS = 60;

//	@Override
//	public Result<Pagination<FieldDicListItemVO>> list4View(Operator operator, FieldDicQueryRequest request) {
//		Result<Pagination<FieldDicListItemVO>> Result = new Result<>();
//
//		SearchGroup searchGroup = new SearchGroup(SearchLogicType.AND);
//		if(StringUtils.isNotBlank(request.getDic())){
//			searchGroup.addSearch(EntityFieldDic.COL_DIC, SearchOperator.Equal, request.getDic());
//		}
//		if(StringUtils.isNotBlank(request.getName())){
//			searchGroup.addSearch(EntityFieldDic.COL_NAME, SearchOperator.Equal, request.getName());
//		}
//		if(StringUtils.isNotBlank(request.getStartCreateTime())){
//			Date startCreateTime = DateUtil.parse(request.getStartCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(EntityFieldDic.COL_CREATE_TIME, SearchOperator.GreaterThanOrEqual, startCreateTime);
//		}
//		if(StringUtils.isNotBlank(request.getEndCreateTime())){
//			Date endCreateTime = DateUtil.parse(request.getEndCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(EntityFieldDic.COL_CREATE_TIME, SearchOperator.LessThan, endCreateTime);
//		}
//		try {
//			Pagination<EntityFieldDic> entitiesPagination = this.entityFieldDicMapper.findEntitiesPagination(null, searchGroup, request.getPageIndex(), request.getPageSize(), String.format("%s desc", EntityDataSource.COL_CREATE_TIME));
//			Pagination<FieldDicListItemVO> pagination = new Pagination<>(request.getPageIndex(), request.getPageSize(), entitiesPagination.getTotalCount());
//			if(CollectionUtils.isNotEmpty(entitiesPagination)) {
//				for (EntityFieldDic entityFieldDic : entitiesPagination) {
//					pagination.add(convertToListItemVo(entityFieldDic));
//				}
//			}
//			return Result.changeSucc(pagination);
//		} catch (Exception e) {
//			logger.error("逻辑表查询失败", e);
//			return Result.changeErr("逻辑表查询失败：" + e.getMessage());
//		}
//	}

//	private FieldDicListItemVO convertToListItemVo(EntityFieldDic entityFieldDic) {
//		FieldDicListItemVO vo = new FieldDicListItemVO();
//		vo.setId(entityFieldDic.getId());
//		vo.setDic(entityFieldDic.getDic());
//		vo.setName(entityFieldDic.getName());
//		vo.setDescription(entityFieldDic.getDescription());
//		vo.setCreatorName(BspService.getBspUserNameById(entityFieldDic.getCreatorId()));
//		vo.setCreateTimeFormat(DateUtil.format(entityFieldDic.getCreateTime()));
//		vo.setModifierName(BspService.getBspUserNameById(entityFieldDic.getModifierId()));
//		vo.setModifyTimeFormat(DateUtil.format(entityFieldDic.getModifyTime()));
//		return vo;
//	}

//	/**
//	 * 详情视图
//	 */
//	@Override
//	public Result<FieldDicDetailVO> detail4View(Operator operator, long id) {
//		Result<FieldDicDetailVO> Result = new Result<>();
//		try {
//			EntityFieldDic entity = entityFieldDicMapper.findEntityById(id);
//			return Result.changeSucc(convertToDetailVo(entity));
//		} catch (Exception e) {
//			logger.error(String.format("逻辑表(%s)查询失败", id), e);
//			return Result.changeErr("逻辑表详情查询失败：" + e.getMessage());
//		}
//	}

//	private FieldDicDetailVO convertToDetailVo(EntityFieldDic entity) {
//		FieldDicDetailVO vo = new FieldDicDetailVO();
//		vo.setId(entity.getId());
//		vo.setDic(entity.getDic());
//		vo.setName(entity.getName());
//		vo.setDescription(entity.getDescription());
//		return vo;
//	}

	/**
	 * 添加通用字典
	 * @param operator 操作人
	 * @param request 请求
	 */
	@Override
	public Result<Long> add(Operator operator, FieldDicRequest request){
		Result<Long> methodResult = new Result<>();
		AssertUtils.argumentBlank(request.getDic(), "必须提供字典Dic(唯一)");
		AssertUtils.argumentBlank(request.getName(), "必须提供字典名称");

		String dic = request.getDic();
		String uniqueKey = LOCK_KEY + dic;
		String requestId = UUID.randomUUID().toString();
		if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)) {
			try {
				EntityFieldDic fieldDic = entityFieldDicMapper.selectByDic(dic);
				if(fieldDic != null){
					return methodResult.changeErr("系统内已存在该通用字典！");
				}

				// 执行添加
				fieldDic = new EntityFieldDic();
				fieldDic.setDic(request.getDic());
				fieldDic.setName(request.getName());
				fieldDic.setDescription(request.getDescription());
				Date now = new Date();
				fieldDic.setCreatorId(operator.getOperatorId());
				fieldDic.setCreateTime(now);
				fieldDic.setModifierId(operator.getOperatorId());
				fieldDic.setModifyTime(now);
				entityFieldDicMapper.insert(fieldDic);
				return methodResult.changeSucc(fieldDic.getId());
			} catch (Exception e){
				log.error("添加通用字典失败", e);
				return methodResult.changeErr("通用字典添加失败，系统异常：" + e.getMessage());
			} finally {
				redisService.releaseLock(uniqueKey, requestId);
			}
		} else {
			return methodResult.changeErr("请不要频繁操作！");
		}
	}

	/**
	 * 更新通用字典
	 * @param operator 操作人
	 * @param fieldDicId 通用字典ID
	 * @param request 请求
	 */
	@Override
	public Result<?> update(Operator operator, long fieldDicId, FieldDicRequest request){
		Result<?> methodResult = new Result<>();

		EntityFieldDic entityFieldDic = entityFieldDicMapper.selectById(fieldDicId);
		AssertUtils.argumentNull(entityFieldDic, "不存在该通用字典！");
		String uniqueKey = LOCK_KEY + (StringUtils.isBlank(request.getDic()) ? entityFieldDic.getDic() : request.getDic());
		String requestId = UUID.randomUUID().toString();
		if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)){
			try {
				if(StringUtils.isNotBlank(request.getDic()) && !request.getDic().equals(entityFieldDic.getDic())){
					EntityFieldDic existFieldDic = entityFieldDicMapper.selectByDic(request.getDic());
					if(existFieldDic != null){
						return methodResult.changeErr(String.format("系统内已存在名称为(%s)的通用字典！", request.getName()));
					}
				}
				entityFieldDic.setName(request.getName());
				entityFieldDic.setDic(request.getDic());
				entityFieldDic.setDescription(request.getDescription());
				Date now = new Date();
				entityFieldDic.setModifierId(operator.getOperatorId());
				entityFieldDic.setModifyTime(now);

				entityFieldDicMapper.updateById(entityFieldDic);
				searchConfigChangeService.triggerByFieldDic(fieldDicId);
			} catch (Exception e){
				log.error(String.format("通用字典（%s）更新异常", fieldDicId));
				return methodResult.changeErr("通用字典更新失败，系统异常：" + e.getMessage());
			} finally {
				redisService.releaseLock(uniqueKey, requestId);
			}
		}

		return methodResult;
	}

	/**
	 * 删除通用字典
	 * @param operator 操作人
	 * @param fieldDicId 通用字典ID
	 */
	@Override
	public Result<?> delete(Operator operator, long fieldDicId){
		Result<?> methodResult = new Result<>();
		EntityFieldDic entityFieldDic = entityFieldDicMapper.selectById(fieldDicId);
		AssertUtils.argumentNull(entityFieldDic, "系统内已不存在该通用字典");

		// 检查是否存在关联自定义字典
		List<EntityLogicTableFieldDic> logicTableFieldDices = entityLogicTableFieldDicMapper.selectByFieldDicId(fieldDicId);
		if(CollectionUtils.isNotEmpty(logicTableFieldDices)){
			Map<Long, List<EntityLogicTableFieldDic>> logicTableFieldDicMap = logicTableFieldDices.stream().collect(Collectors.groupingBy(EntityLogicTableFieldDic::getLogicTableId));
			List<String> alertTips = Lists.newArrayList();
			for (Map.Entry<Long, List<EntityLogicTableFieldDic>> entry : logicTableFieldDicMap.entrySet()) {
				EntityLogicTable logicTable = entityLogicTableMapper.selectById(entry.getKey());
				String fieldNames = entry.getValue().stream().map(EntityLogicTableFieldDic::getDic).collect(Collectors.joining(","));
				alertTips.add(String.format("%s(%s)", logicTable.getName(), fieldNames));
			}
			return methodResult.changeErr("存在关联的逻辑表自定义字典：" + StringUtils.join(alertTips, ", "));
		}

		// 检查是否存在关联取数器
		List<SearchResultFetcherFieldDicRelation> fetcherFieldDicRelations = searchResultFetcherFieldDicRelationMapper.selectByFieldDicId(fieldDicId);
		if(CollectionUtils.isNotEmpty(fetcherFieldDicRelations)){
			List<Long> fetcherIds = fetcherFieldDicRelations.stream().map(SearchResultFetcherFieldDicRelation::getFetcherId).distinct().collect(Collectors.toList());
			List<SearchResultFetcher> searchResultFetchers = searchResultFetcherMapper.selectList(new QueryWrapper<SearchResultFetcher>().lambda().in(SearchResultFetcher::getId, fetcherIds));
			List<String> alertTips = searchResultFetchers.stream().map(input -> String.format("%s(%s)", input.getName(), input.getDic())).collect(Collectors.toList());
			return methodResult.changeErr("存在关联的取数器：" + StringUtils.join(alertTips, ", "));
		}

		// 检查是否存在关联场景
		List<SearchSceneConfig> searchSceneConfigs = searchSceneConfigMapper.selectByFieldDicId(fieldDicId);
		if(CollectionUtils.isNotEmpty(searchSceneConfigs)){
			List<Long> sceneIds = searchSceneConfigs.stream().map(SearchSceneConfig::getSceneId).distinct().collect(Collectors.toList());
			List<SearchScene> searchScenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
			List<String> alertTips = searchScenes.stream().map(input -> String.format("%s(%s)", input.getName(), input.getCode())).collect(Collectors.toList());
			return methodResult.changeErr("存在关联的查询场景：" + StringUtils.join(alertTips, ", "));
		}

		// 检查是否存在内置取数器关联字段
		List<SearchSceneInnerFetcherFieldConfig> innerFetcherFieldConfigs = searchSceneInnerFetcherFieldConfigMapper.selectByFieldDicId(fieldDicId);
		if(CollectionUtils.isNotEmpty(innerFetcherFieldConfigs)) {
			List<Long> sceneInnerFetcherConfigIds = innerFetcherFieldConfigs.stream().map(SearchSceneInnerFetcherFieldConfig::getSceneInnerFetcherConfigId).distinct().collect(Collectors.toList());
			List<SearchSceneInnerFetcherConfig> sceneInnerFetcherConfigs = searchSceneInnerFetcherConfigMapper.selectList(new QueryWrapper<SearchSceneInnerFetcherConfig>().lambda().in(SearchSceneInnerFetcherConfig::getId, sceneInnerFetcherConfigIds));
			Map<Long, List<SearchSceneInnerFetcherConfig>> sceneConfigMap = sceneInnerFetcherConfigs.stream().collect(Collectors.groupingBy(SearchSceneInnerFetcherConfig::getSceneId));
			List<String> alertTips = Lists.newArrayList();
			for (Map.Entry<Long, List<SearchSceneInnerFetcherConfig>> entry : sceneConfigMap.entrySet()) {
				SearchScene searchScene = searchSceneMapper.selectById(entry.getKey());
				alertTips.add(String.format("%s(%s)", searchScene.getName(), entry.getValue().stream().map(SearchSceneInnerFetcherConfig::getDic).collect(Collectors.joining(","))));
			}
			return methodResult.changeErr("存在关联的查询场景下内置取数器：" + StringUtils.join(alertTips, ", "));
		}

		// 检查场景的预设条件中是否关联了该字典
		List<SearchScenePresetConditionConfig> presetConditionConfigs = searchScenePresetConditionConfigMapper.selectByFieldDicId(fieldDicId);
		if(CollectionUtils.isNotEmpty(presetConditionConfigs)) {
			List<Long> sceneIds = presetConditionConfigs.stream().map(SearchScenePresetConditionConfig::getSceneId).distinct().collect(Collectors.toList());
			List<SearchScene> searchScenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
			List<String> alertTips = searchScenes.stream().map(input -> String.format("%s(%s)", input.getName(), input.getCode())).collect(Collectors.toList());
			return methodResult.changeErr("场景的预设查询条件中依赖了该字典：" + StringUtils.join(alertTips, ", "));
		}

		// 执行删除
		entityFieldDicMapper.deleteById(fieldDicId);

		return methodResult;
	}

//	@Override
//	public Result<List<FieldDicListItemVO>> byLogicTableId4View(Operator operator, long logicTableId) {
//		Result<List<FieldDicListItemVO>> Result = new Result<>();
//
//		try {
//			List<FieldDicListItemVO> vos = Lists.newArrayList();
//			List<EntityLogicTableFieldDic> entityLogicTableFieldDices = entityLogicTableFieldDicMapper.selectByLogicTableId(logicTableId);
//			if(CollectionUtils.isNotEmpty(entityLogicTableFieldDices)) {
//				Map<Long, EntityLogicTableFieldDic> logicTableFieldDicMap = entityLogicTableFieldDices.stream().collect(Collectors.toMap(EntityLogicTableFieldDic::getFieldDicId, v -> v));
//				List<EntityFieldDic> fieldDices = entityFieldDicMapper.findEntitiesByIds(Lists.newArrayList(logicTableFieldDicMap.keySet()));
//				if(CollectionUtils.isNotEmpty(fieldDices)) {
//					for (EntityFieldDic fieldDic : fieldDices) {
//						FieldDicListItemVO fieldDicListItemVO = convertToListItemVo(fieldDic);
//						vos.add(fieldDicListItemVO);
//					}
//				}
//			}
//
//			return Result.changeSucc(vos);
//		} catch (Exception e) {
//			logger.error(String.format("获取逻辑表(%s)关联的通用字典失败", logicTableId), e);
//			return Result.changeErr("获取逻辑表关联的通用字典失败");
//		}
//
//	}

}
